package com.quanyan.common.utils;


import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * @Author Hugo.Wwg
 * @Since 2016-04-14
 */
public class SerializeUtils {

	private static Logger logger = LoggerFactory.getLogger(SerializeUtils.class);

	/**
	 * 序列化对象
	 */
	public static byte[] serialize(Object object) {
		Kryo kryo = getKryo();
		Output output = null;
		try {
			output = new Output(1, 102400);
			kryo.writeClassAndObject(output, object);
			byte[] bytes = output.toBytes();
			output.flush();
			return bytes;
		} catch (Exception e) {
			logger.error(ObjectUtil.getFullStackTraceToString(e));
			throw new RuntimeException(e);
		}
	}

	/**
	 * 序列化对象
	 */
	public static <T> byte[] serialize(Object object, Class<T> type) {
		Kryo kryo = getKryo();
		Output output = null;
		try {
			output = new Output(1, 102400);
			kryo.writeObjectOrNull(output, object, type);
			byte[] bytes = output.toBytes();
			output.flush();
			return bytes;
		} catch (Exception e) {
			logger.error(ObjectUtil.getFullStackTraceToString(e));
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}

	/**
	 * 反序列化
	 */
	public static <T> T deserialize(byte[] bytes) {
		if (bytes == null) {
			return null;
		}
		try {
			Kryo kryo = getKryo();
			Input input = new Input(bytes);
			@SuppressWarnings("unchecked")
			T t = (T) kryo.readClassAndObject(input);
			input.close();
			return t;
		} catch (Exception e) {
			logger.error(ObjectUtil.getFullStackTraceToString(e));
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}

	public static <T> T deserialize(byte[] bytes, Class<T> type) {
		if (bytes == null) {
			return null;
		}
		try {
			Kryo kryo = getKryo();
			Input input = new Input(bytes);
			T obj = kryo.readObject(input, type);
			input.close();
			return obj;
		} catch (Exception e) {
			logger.error(ObjectUtil.getFullStackTraceToString(e));
			throw new RuntimeException(e);
		}
	}


	private static Kryo getKryo(){ //TODO 用池的方式
		Kryo kryo = new Kryo();
		kryo.setRegistrationRequired(false);
	    kryo.setMaxDepth(20);
		kryo.setClassLoader(SerializeUtils.class.getClassLoader());
		return kryo;
	}
}
